fix: remove defs when ref already defined in schema#888
fix: remove defs when ref already defined in schema#888gurgunday merged 2 commits intofastify:mainfrom
Conversation
- Remove $defs from schema keys if $ref key already exists when converting json schema into openapi 3. This fixes issue in openapi generation when using TypeBox modules to define schema. - Add test case for refs.
There was a problem hiding this comment.
Pull Request Overview
This PR removes redundant $defs when an object schema already contains a $ref, preventing duplicate definitions in the generated OpenAPI output. It adds a guard in the convertJsonSchemaToOpenapi3 utility to drop $defs when $ref is present and includes a new test to verify this behavior.
- Strip
$defswhen$refis detected in schema conversion - Add a test case to confirm only the
$refremains and definitions are not duplicated
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/spec/openapi/utils.js | Added a check to delete $defs if $ref exists in the schema |
| test/spec/openapi/refs.test.js | New test to validate that only $ref is returned when both keys are present |
Comments suppressed due to low confidence (1)
test/spec/openapi/refs.test.js:561
- Consider adding an assertion that the final component schemas do not contain any
$defskeys to ensure the removal logic is fully covered.
t.assert.deepStrictEqual(openapiObject.paths['/person'].get.responses[200].content, expectedPathContent)
ivan-tymoshenko
left a comment
There was a problem hiding this comment.
-
Hi, I don't agree with a statement
if $ref key is defined for object there shouldn't exist other keys on the object. I would say the correct one isAny sibling elements of a $ref are ignored., so this is still a valid schema. -
Why do you remove only
$defsthen and not all other properties except$ref? -
My problem with this change is that it might break some references. For example you can define a schema in the $defs that would have a global id
$id: Book. If someone has a ref to this schema$ref: Bookit will be broken after this change.
Although the change seems logical, I fear it could break the code in cases where people (including us) don't follow the spec exactly.
|
Seems logical that there should be no siblings for $ref. I could change this to remove all other keys if that follows the spec more closely? I've created this change because we are using TypeBox to create schemas for our routes and without the change the openapi.json size grows quite large as we have large number of shared types between our routes. I don't quite understand your how you are using this in a way that doesn't follow OpenAPI specification? |
|
Sorry, I misunderstood the place where the change is done. For the openapi v3 schemas only it should be fine. Please remove all properties to be consistent (not only $defs). |
- Remove sibling keys if $refs exits on openapi 3 json schema.
|
I updated the code to remove siblings if |
|
Is it possible to get this merged or are there some steps that need to be done before that? |
|
Ping. Would It be possible to get this merged and released? |
|
Obviously it's too late now, but I just need to say this was an absolutely brutal change to make as part of a patch release. When my package.json has Sure, the result adheres closer to how the spec defines a $ref, but many tools (including Swagger UI!) don't seem to follow those refs properly. For example, the params for a simple GET: Is that Swagger UI's fault? Of course. Regardless, this stinks. |
|
Are you saying that someone should open an issue at https://github.com/swagger-api/swagger-ui or that there is some other issue on https://github.com/fastify/fastify-swagger-ui ? In any case I would suggest to create a dedicated issue for that. |


When using TypeBox Modules to define Fastify schemas the current implementation duplicates definitions even when using
fastify.addSchema(schema). This causes the openapi schema file to be larger and contain duplicate definitions.If I am correct the OpenApi specification defines that if
$refkey is defined for object there shouldn't exist other keys on the object (meaning$defsshouldn't be there). That is why I've added extra check toconvertJsonSchemaToOpenapi3to remove$defs-key if$refs-key exits.I'm open to suggestions if there's a more appropriate way to resolve this.
Usage example with TypeBox modules:
schema.ts
index.ts
After the change and using the above style TypeBox module schema definition results in following openapi json:
{ .... "components": { "schemas": { "def-0": { "humanModule": { "$defs": { "AddressSchema": { "type": "object", "properties": { "street": { "type": "string" }, "streetNumber": { "type": "number" } }, "required": ["street", "streetNumber"], "title": "AddressSchema" }, "PersonSchema": { "type": "object", "properties": { "name": { "type": "string" }, "homeAddress": { "$ref": "#/components/schemas/def-1" }, "workAddress": { "$ref": "#/components/schemas/def-1" } }, "required": ["name", "homeAddress", "workAddress"], "title": "PersonSchema" }, "PostRequestSchema": { "type": "object", "properties": { "person": { "$ref": "#/components/schemas/def-2" } }, "required": ["person"], "title": "PostRequestSchema" } } }, "title": "common" }, "def-1": { "type": "object", "properties": { "street": { "type": "string" }, "streetNumber": { "type": "number" } }, "required": ["street", "streetNumber"], "title": "AddressSchema" }, "def-2": { "type": "object", "properties": { "name": { "type": "string" }, "homeAddress": { "$ref": "#/components/schemas/def-1" }, "workAddress": { "$ref": "#/components/schemas/def-1" } }, "required": ["name", "homeAddress", "workAddress"], "title": "PersonSchema" }, "def-3": { "type": "object", "properties": { "person": { "$ref": "#/components/schemas/def-2" } }, "required": ["person"], "title": "PostRequestSchema" } } }, "paths": { "/person": { "get": { "responses": { "200": { "description": "Default Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/def-2" } } } } } } } } .... }This PR should fix issue related to #854
Related issue on TypeBox repository: sinclairzx81/typebox#1283
Checklist
npm run test && npm run benchmark --if-presentand the Code of conduct